package com.cy.guava;

import com.google.common.collect.*;
import org.testng.annotations.Test;

import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.testng.Assert.*;

/**
 * @author yue.cao
 * @since 11-11-2020
 * <p>
 * 1	Set<Table.Cell<R,C,V>> cellSet()
 * 返回集合中的所有行键/列键/值三元组。
 * 2	void clear()
 * 从表中删除所有映射。
 * 3	Map<R,V> column(C columnKey)
 * 返回在给定列键的所有映射的视图。
 * 4	Set<C> columnKeySet()
 * 返回一组具有表中的一个或多个值的列键。
 * 5	Map<C,Map<R,V>> columnMap()
 * 返回关联的每一列键与行键对应的映射值的视图。
 * 6	boolean contains(Object rowKey, Object columnKey)
 * 返回true，如果表中包含与指定的行和列键的映射。
 * 7	boolean containsColumn(Object columnKey)
 * 返回true，如果表中包含与指定列的映射。
 * 8	boolean containsRow(Object rowKey)
 * 返回true，如果表中包含与指定的行键的映射关系。
 * 9	boolean containsValue(Object value)
 * 返回true，如果表中包含具有指定值的映射。
 * 10	boolean equals(Object obj)
 * 比较指定对象与此表是否相等。
 * 11	V get(Object rowKey, Object columnKey)
 * 返回对应于给定的行和列键，如果没有这样的映射存在值，返回null。
 * 12	int hashCode()
 * 返回此表中的哈希码。
 * 13	boolean isEmpty()
 * 返回true，如果表中没有映射。
 * 14	V put(R rowKey, C columnKey, V value)
 * 关联指定值与指定键。
 * 15	void putAll(Table<? extends R,? extends C,? extends V> table)
 * 复制从指定的表中的所有映射到这个表。
 * 16	V remove(Object rowKey, Object columnKey)
 * 如果有的话，使用给定键相关联删除的映射。
 * 17	Map<C,V> row(R rowKey)
 * 返回包含给定行键的所有映射的视图。
 * 18	Set<R> rowKeySet()
 * 返回一组行键具有在表中的一个或多个值。
 * 19	Map<R,Map<C,V>> rowMap()
 * 返回关联的每一行按键与键列对应的映射值的视图。
 * 20	int size()
 * 返回行键/列键/表中的值映射关系的数量。
 * 21	Collection<V> values()
 * 返回所有值，其中可能包含重复的集合。
 */
public class DemoWithGuavaTable {


	@Test(description = "create")
	public void t0() {
		Table<String, String, Integer> table;
		// 使用HashBasedTable 类的create方法，其内部使用LinkedHashMap 类
		table = HashBasedTable.create();

		// 如果我们需要Table的行key和列key有序（按自然顺序或提供的比较器排序），可以使用TreeBasedTable的create方法，其内部使用TreeMap：
		table = TreeBasedTable.create();

		// 如何事先就确定行key和列可以，且table大小固定，可以使用ArrayTable的create方法：
		List<String> rows = Lists.newArrayList("张三", "李四");
		List<String> columns = Lists.newArrayList("搬砖", "写代码", "和水泥");
		table = ArrayTable.create(rows, columns);

		// 如果需要创建不可变的table实例，其内部数据不能修改，可以使用ImmutableTable 类，使用其builder：
		table = ImmutableTable.<String, String, Integer>builder().put("张三", "搬砖", 120).build();
	}

	@Test(description = "modify")
	public void t1() {
		Table<String, String, Integer> table = HashBasedTable.create();
		table.put("张三", "搬砖", 120);
		table.put("张三", "写代码", 60);
		table.put("李四", "和水泥", 60);
		table.put("李四", "写代码", 120);
		table.put("Cy", "写代码", 666);

		// 获取值
		assertEquals(table.get("张三", "写代码"), new Integer(60));
		assertEquals(table.get("李四", "写代码"), new Integer(120));

		// 判断是否存在
		assertTrue(table.contains("张三", "写代码"));
		assertTrue(table.containsColumn("写代码"));
		assertTrue(table.containsRow("张三"));
		assertTrue(table.containsValue(60));

		// 删除
		assertEquals(table.remove("Cy", "写代码"), new Integer(666));
		assertNull(table.remove("Cy", "写代码"));
		System.out.println(table.column("写代码"));
		System.out.println(table.row("张三"));

		// 转换
		System.out.println("columnMap -> " + table.columnMap());
		System.out.println("rowMap -> " + table.rowMap());
		System.out.println("rowKeySet ->" + table.rowKeySet());
		System.out.println("columnKeySet ->" + table.columnKeySet());
	}

	@Test(description = "一个例子")
	public void t2() {
		Table<String, String, String> employeeTable = HashBasedTable.create();
		//initialize the table with employee details
		employeeTable.put("IBM", "101", "Mahesh");
		employeeTable.put("IBM", "102", "Ramesh");
		employeeTable.put("IBM", "103", "Suresh");

		employeeTable.put("Microsoft", "111", "Sohan");
		employeeTable.put("Microsoft", "112", "Mohan");
		employeeTable.put("Microsoft", "113", "Rohan");

		employeeTable.put("TCS", "121", "Ram");
		employeeTable.put("TCS", "102", "Shyam");
		employeeTable.put("TCS", "123", "Sunil");

		// 所有行数据
		System.out.println("所有行数据" + employeeTable.cellSet());
		// 所有公司
		System.out.println("所有公司" + employeeTable.rowKeySet());
		// 所有员工编号
		System.out.println("所有员工编号" + employeeTable.columnKeySet());
		// 所有员工名称
		System.out.println("所有员工名称->" + employeeTable.values());
		// 公司中的所有员工和员工编号
		System.out.println("公司中的所有员工和员工编号->" + employeeTable.rowMap());
		// 员工编号对应的公司和员工名称
		System.out.println("员工编号对应的公司和员工名称->" + employeeTable.columnMap());
		// row+column对应的value
		System.out.println(employeeTable.get("IBM", "101"));
		// IBM公司中所有信息
		Map<String, String> ibmEmployees = employeeTable.row("IBM");

		System.out.println("IBM公司中所有信息");
		for (Map.Entry<String, String> entry : ibmEmployees.entrySet()) {
			System.out.println("Emp Id: " + entry.getKey() + ", Name: " + entry.getValue());
		}

		// table中所有的不重复的key
		Set<String> employers = employeeTable.rowKeySet();
		System.out.print("Employers: ");
		for (String employer : employers) {
			System.out.print(employer + " ");
		}
		System.out.println();

		// 得到员工编号为102的所有公司和姓名
		Map<String, String> EmployerMap = employeeTable.column("102");
		for (Map.Entry<String, String> entry : EmployerMap.entrySet()) {
			System.out.println("Employer: " + entry.getKey() + ", Name: " + entry.getValue());
		}
	}
}
